package org.boot.easyapi.core.service.table.impl;

import lombok.extern.slf4j.Slf4j;
import org.boot.easyapi.util.jdbc.JdbcUtil;
import org.boot.easyapi.pojo.db.DbDTO;
import org.boot.easyapi.pojo.db.TableDTO;
import org.boot.easyapi.core.cache.CacheRedisDAO;
import org.boot.easyapi.core.service.table.TableService;
import org.boot.easyapi.util.CollUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static org.boot.easyapi.exception.BusinessException.exception;

@Slf4j
@Service("easyapi-tableService")
public class TableServiceImpl implements TableService {
    
    public final static Map<String, String> defaultFields = new LinkedHashMap<String, String>() {{
        put("id", "bigint NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID(系统字段)'");
        put("creator", "varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者(系统字段)'");
        put("create_time", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(系统字段)'");
        put("createTime", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(系统字段)'");
        put("updater", "varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者(系统字段)'");
        put("update_time", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(系统字段)'");
        put("updateTime", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(系统字段)'");
        put("deleted", "bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(系统字段)'");
        put("tenant_id", "bigint NOT NULL DEFAULT 0 COMMENT '租户编号(系统字段)'");
        put("tenantId", "bigint NOT NULL DEFAULT 0 COMMENT '租户编号(系统字段)'");
    }};

    public final static Map<String, String> defaultCreateFields = new LinkedHashMap<String, String>() {{
        put("id", "bigint NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID(系统字段)'");
        put("creator", "varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者(系统字段)'");
        put("create_time", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(系统字段)'");
        put("updater", "varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者(系统字段)'");
        put("update_time", "datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(系统字段)'");
        put("deleted", "bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除(系统字段)'");
        put("tenant_id", "bigint NOT NULL DEFAULT 0 COMMENT '租户编号(系统字段)'");
    }};

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource(name = "easyapi-cacheRedisDAO")
    private CacheRedisDAO cacheRedisDAO;


    @Override
    public void createTable(Map<String, Object> tableInfo) {
        String tableName = (String) tableInfo.get("tableName");
        checkTableName(tableName);

        StringBuilder sql = new StringBuilder("CREATE TABLE " + tableName + " (");
        // 解析字段信息
        Map<String, String> fields = (Map<String, String>) tableInfo.get("fields");
        //添加默认建表字段
        for (Map.Entry<String, String> entry : defaultCreateFields.entrySet())  {
            sql.append(entry.getKey()).append(" ").append(entry.getValue()).append(",");
        }
        for (Map.Entry<String, String> entry : fields.entrySet())  {
            // 跳转系统字段，进入下一次循环
            if(defaultFields.containsKey(entry.getKey().toLowerCase())){
                continue;
            }
            sql.append(entry.getKey()).append(" ").append(entry.getValue()).append(",");
        }
        sql.delete(sql.length()  - 1, sql.length());  // 移除最后一个逗号和空格
        sql.append(")");

        try{
            jdbcTemplate.execute(sql.toString());
        } catch (Exception e) {
            throw exception("表:" + tableName + "，创建错误！原因：" + e.getMessage());
        }
    }

    @Override
    public DbDTO getDbType() {
        DbDTO db = cacheRedisDAO.getDb();
        db.setDbUrl(null);
        db.setDbUserName(null);
        db.setDbName(null);
        return db;
    }


    @Override
    public List<String> getTableList() {
        return cacheRedisDAO.getTables().keySet().stream().collect(Collectors.toList());
    }

    @Override
    public List<TableDTO> getTable(String tableName) {
        return cacheRedisDAO.getTable(tableName, true);
    }

    @Override
    public List<String> getTableFields(String tableName) {
        List<TableDTO> table = cacheRedisDAO.getTable(tableName, true);
        return table.stream().map(TableDTO::getName).collect(Collectors.toList());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean upSystemTable(String table) {
        List<TableDTO> tableDTOS = JdbcUtil.getTable(table);
        if(CollUtil.isEmpty(tableDTOS)) throw exception("表:" + table + "，不存在！");

        //增加系统字段
//        String insertDefaultId = "ALTER TABLE " + table + " ADD COLUMN id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID(系统字段)';";
        String insertDefaultCreator = "ALTER TABLE " + table + " ADD COLUMN creator VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者(系统字段)';";
        String insertDefaultCreateTime = "ALTER TABLE " + table + " ADD COLUMN create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间(系统字段)';";
        String insertDefaultUpdater = "ALTER TABLE " + table + " ADD COLUMN updater VARCHAR(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者(系统字段)';";
        String insertDefaultUpdateTime = "ALTER TABLE " + table + " ADD COLUMN update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(系统字段)';";
        String insertDefaultDeleted = "ALTER TABLE " + table + " ADD COLUMN deleted VARCHAR(50) NOT NULL COMMENT '是否删除(系统字段)';";
        String insertDefaultTenantId = "ALTER TABLE " + table + " ADD COLUMN tenant_id VARCHAR(50) NOT NULL COMMENT '租户编号(系统字段)';";

        //声明为map
        Map<String, String> upSqlMap = new LinkedHashMap<>();
//        upSqlMap.put("id", insertDefaultId);
        upSqlMap.put("creator", insertDefaultCreator);
        upSqlMap.put("create_time", insertDefaultCreateTime);
        upSqlMap.put("updater", insertDefaultUpdater);
        upSqlMap.put("update_time", insertDefaultUpdateTime);
        upSqlMap.put("deleted", insertDefaultDeleted);
        upSqlMap.put("tenant_id", insertDefaultTenantId);

        for (Map.Entry<String, String> entry : upSqlMap.entrySet()) {
            try{
                jdbcTemplate.execute(entry.getValue());
            } catch (Exception e) {
                if (e.getCause().toString().contains("Duplicate column name")) {
                    throw exception("表:" + table + "中，已存在[" + entry.getKey() + "]字段！");
                }
//                else if(e.getCause().toString().contains("Multiple primary key defined")){
//                    throw exception("表:" + table + "中，已存在唯一主键，请取消表中主键为非主键后重试！");
//                }
                else {
                    throw exception("表:" + table + "中，字段:" + entry.getKey() + "，补充错误！原因：" + e.getLocalizedMessage());
                }
            }
        }
        return true;
    }












    private void checkTableName(String tableName) {
        List<TableDTO> table = this.getTable(tableName);
        if(CollUtil.isNotEmpty(table)){
            throw exception("表:" + tableName + "，已存在！");
        }
    }
}
